package de.karnik.dokobu.controllers;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;
import javax.servlet.http.HttpServletRequest;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.StopAnalyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.de.GermanAnalyzer;
import org.apache.lucene.analysis.snowball.SnowballAnalyzer;
import org.apache.lucene.analysis.tokenattributes.TermAttribute;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.google.appengine.api.datastore.Key;

import de.karnik.dokobu.persistence.Ingredient;
import de.karnik.dokobu.persistence.IngredientDao;
import de.karnik.dokobu.persistence.IngredientIndex;

@Controller
@RequestMapping(value="/ingredients")
public class IngredientsController extends BaseController {

	 @RequestMapping( method = RequestMethod.GET )
	 public String show( HttpServletRequest request, ModelMap model ) {
		 this.init();
		 
		 IngredientDao id = IngredientDao.getInstance();
		
		 this.getBaseAttributes().put( "title",  "Zutaten" );
		 this.getBaseAttributes().put( "ingredients",  id.getAll() );
		 
		 this.getBaseAttributes().put( "content", "ingredients" );
		 model.mergeAttributes( this.getBaseAttributes() );
		 
		 
		 
		 return "ingredients/show";
	 }
	 
	 @RequestMapping( value = "/add", method = RequestMethod.POST )
	 public @ResponseBody Ingredient create( @RequestParam("name") String name, HttpServletRequest request, ModelMap model ) {
		 		 
		 IngredientDao id = IngredientDao.getInstance();
		 List<Ingredient> iList;
		 Ingredient ingredient;
		 IngredientIndex iIndex;
		 
		 Query query = id.getPersistenceManager().newNamedQuery( Ingredient.class, "Ingredient_GetByName" );

		 if( ( iList = (List<Ingredient>)query.execute( name )  ).size() == 0 ) {
			 
			 Transaction tx = id.getPersistenceManager().currentTransaction();
			 tx.begin();
			 ingredient = new Ingredient();
			 iIndex = new IngredientIndex();
			 iIndex.setIndex( getIndex( name, 50 ) );
			 
			 ingredient.setName( name );
			 ingredient.setIndex( iIndex );
			 
			 id.save( ingredient );
			 tx.commit();
			 
		 } else {
			 return iList.get( 0 );
		 }
		  
		 return ingredient;
	 }
	 
	 @ModelAttribute("ingredients")
	 @RequestMapping( value = "/search", method = RequestMethod.GET )
	 public @ResponseBody List<Ingredient> getIngredients( 	@RequestParam String searchString, 
			 												@RequestParam int start, 
			 												@RequestParam int count ) throws IOException {    
		 
		 IngredientDao id = IngredientDao.getInstance(); 
		 
		 //searchString = ( searchString != null ? searchString.toLowerCase() : "").trim();
		 
		 //Query query = id.getPersistenceManager().newNamedQuery( Ingredient.class, "Ingredient_SearchByName" );

		 //List<Ingredient> ingredients = (List<Ingredient>)query.execute( searchString, searchString + "\ufffd" );
		 
		 return searchIngredients( searchString, 0L );
		 
		 //return ingredients;
	 }
	 
	 protected Set<String> getIndex( String input, int maxTokens ) {
		 Set<String> returnSet = new HashSet<String>();
		 
		 if( input.length() < maxTokens )
			 maxTokens = input.length();
			 
		 for( int i = 1; i < ( maxTokens + 1 ); i++ )
			 returnSet.add( input.substring( 0, i ) );
		 
		 return returnSet;
	 }
	 /*
	 protected Set<String> getIndex( String input, int maxTokens ) {
		 Set<String> returnSet = new HashSet<String>();
		 try {
			 
			 
			 
			 GermanAnalyzer analyzer =  new GermanAnalyzer( org.apache.lucene.util.Version.LUCENE_30 );
			 //SnowballAnalyzer analyzer =  new SnowballAnalyzer (org.apache.lucene.util.Version.LUCENE_30, "German2", org.apache.lucene.analysis.de.GermanAnalyzer.getDefaultStopSet() );
			 //Analyzer analyzer =  new SnowballAnalyzer( org.apache.lucene.util.Version.LUCENE_30, "English", StopAnalyzer.ENGLISH_STOP_WORDS_SET );
			 TokenStream tokenStream = analyzer.tokenStream( "content", new StringReader(input) );
			 while ( tokenStream.incrementToken() && (returnSet.size() < maxTokens) ) {
				 if( tokenStream.hasAttribute( TermAttribute.class ) ) {
					 TermAttribute attr = tokenStream.getAttribute( TermAttribute.class );
					 System.out.println(  attr.term()  );
					 returnSet.add( attr.term() );
				 }
			 }
		 }catch( Exception exc ) {
			 exc.printStackTrace();
		 }
		 return returnSet;
	 }
	 */
	 public List<Ingredient> searchIngredients( String search1, Long entityId ) throws IOException {
		 IngredientDao id = IngredientDao.getInstance(); 
		 PersistenceManager pm = id.getPersistenceManager();
		 Set<String> search = getIndex( search1, 3 );
		 Query query = pm.newQuery("SELECT id FROM " + IngredientIndex.class.getName() );
		 query.setFilter("index == param0");
		 query.declareParameters("String param0");

		 Query query2 = pm.newQuery( Ingredient.class );
		 query2.setFilter("id == keyParam");
		 query2.declareParameters("com.google.appengine.api.datastore.Key keyParam");

		 List<Ingredient> ingredients = null;
		 List<Key> keys;
		 List<Key> parents = new ArrayList<Key>();

		 try {
			 keys = ( List<Key> )query.execute( search );
			 for( Key k : keys){
				 parents.add( k.getParent() );
			 }
			 ingredients = ( List<Ingredient> )query2.execute( parents );
			 

		 } catch ( Exception exc ) {
			 exc.printStackTrace();
		 } finally {
			 query.closeAll();
			 query2.closeAll();
			 //pm.close();
		 }
		 
		 return ingredients;
	 }
}
